package cn.iocoder.yudao.module.system.service.dict.impl;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExtListReqVO;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExtSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataExtDO;
import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataExtMapper;
import cn.iocoder.yudao.module.system.service.dict.DictDataExtService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.DEPT_EXITS_CHILDREN;

@Service
public class DictDataExtServiceImpl implements DictDataExtService {

    @Resource
    private DictDataExtMapper dictDataExtMapper;

    @Override
    public Long createDictDataExt(DictDataExtSaveReqVO createReqVO) {
        if (createReqVO.getParentId() == null) {
            createReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
        }

        // 插入部门
        DictDataExtDO dept = BeanUtils.toBean(createReqVO, DictDataExtDO.class);
        dictDataExtMapper.insert(dept);
        return dept.getId();
    }

    @Override
    public void updateDictDataExt(DictDataExtSaveReqVO updateReqVO) {
        if (updateReqVO.getParentId() == null) {
            updateReqVO.setParentId(DeptDO.PARENT_ID_ROOT);
        }
        // 更新部门
        DictDataExtDO updateObj = BeanUtils.toBean(updateReqVO, DictDataExtDO.class);
        dictDataExtMapper.updateById(updateObj);
    }

    @Override
    public void deleteDictDataExt(Long id) {
        // 校验是否有子部门
        if (dictDataExtMapper.selectCountByParentId(id) > 0) {
            throw exception(DEPT_EXITS_CHILDREN);
        }
        // 删除部门
        dictDataExtMapper.deleteById(id);
    }

    @Override
    public DictDataExtDO getDictDataExt(Long id) {
        return dictDataExtMapper.selectById(id);
    }

    @Override
    public List<DictDataExtDO> getDictDataExtList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return dictDataExtMapper.selectBatchIds(ids);
    }

    @Override
    public List<DictDataExtDO> getDictDataExtList(DictDataExtListReqVO reqVO) {
        List<DictDataExtDO> list = dictDataExtMapper.selectList(reqVO);
        list.sort(Comparator.comparing(DictDataExtDO::getSort));
        return list;
    }

    @Override
    public List<DictDataExtDO> getDictDataTree() {
        List<DictDataExtDO> allNodes = dictDataExtMapper.selectList(new DictDataExtListReqVO());
        return buildTree(allNodes, 0L);
    }

    @Override
    public List<DictDataExtDO> getChildren(Long parentId) {
        return dictDataExtMapper.selectByParentId(parentId);
    }

    @Override
    public DictDataExtDO getParent(Long id) {
        DictDataExtDO current = dictDataExtMapper.selectById(id);
        if (current == null || current.getParentId() == null || current.getParentId() == 0) {
            return null;
        }
        return dictDataExtMapper.selectById(current.getParentId());
    }

    @Override
    public Integer getLevel(Long id) {
        int level = 0;
        DictDataExtDO current = dictDataExtMapper.selectById(id);
        while (current != null && current.getParentId() != null && current.getParentId() != 0) {
            level++;
            current = dictDataExtMapper.selectById(current.getParentId());
        }
        return level;
    }

    @Override
    public List<DictDataExtDO> getChildrenByParentId(Long parentId) {
        DictDataExtDO rootNode = dictDataExtMapper.selectById(parentId);
        if (rootNode == null) {
            return new ArrayList<>();
        }
        return findAllChildren(rootNode.getId());
    }


    private List<DictDataExtDO> findAllChildren(Long parentId) {
        List<DictDataExtDO> result = new ArrayList<>();
        List<DictDataExtDO> children = dictDataExtMapper.selectByParentId(parentId);
        for (DictDataExtDO child : children) {
            result.add(child);
            result.addAll(findAllChildren(child.getId()));
        }
        return result;
    }

    private List<DictDataExtDO> buildTree(List<DictDataExtDO> nodes, Long parentId) {
        return nodes.stream()
                .filter(node -> parentId.equals(node.getParentId()))
                .peek(node -> node.setChildren(buildTree(nodes, node.getId())))
                .collect(Collectors.toList());
    }


    @Override
    public DictDataExtDO parseDictData(String dictType, String label) {
        return dictDataExtMapper.selectByDictTypeAndLabel(dictType, label);
    }

    @Override
    public DictDataExtDO getDictData(String dictType, String value) {
        return dictDataExtMapper.selectByDictTypeAndValue(dictType, value);
    }

}